package com.ethink.warehouse.facade.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ethink.framework.common.constant.CommonRespCode;
import com.ethink.framework.common.exception.BusinessException;
import com.ethink.warehouse.api.MateInventorySaleChannelChangeLogFacade;
import com.ethink.warehouse.api.enums.LogisticsTraceDetailOrderTypeEnum;
import com.ethink.warehouse.api.enums.MateInventorySaleChannelChangeLogOrderStatusEnum;
import com.ethink.warehouse.api.enums.SubjectEnum;
import com.ethink.warehouse.api.info.MateInventorySaleChannelChangeLogInfo;
import com.ethink.warehouse.api.info.MateInventorySaleChannelChangeLogModeInfo;
import com.ethink.warehouse.api.request.MateInventoryLockLogAddRequest;
import com.ethink.warehouse.api.request.MateInventorySaleChannelChangeLogAddRequest;
import com.ethink.warehouse.api.request.MateInventorySaleChannelChangeLogQueryRequest;
import com.ethink.warehouse.api.request.MateInventorySaleChannelChangeLogUpdateRequest;
import com.ethink.warehouse.api.response.MateInventorySaleChannelChangeLogAddResponse;
import com.ethink.warehouse.api.response.MateInventorySaleChannelChangeLogDeleteResponse;
import com.ethink.warehouse.api.response.MateInventorySaleChannelChangeLogGetDetailResponse;
import com.ethink.warehouse.api.response.MateInventorySaleChannelChangeLogUpdateResponse;
import com.ethink.warehouse.common.entity.MateInventorySaleChannelChangeLog;
import com.ethink.warehouse.common.entity.MateInventorySaleChannelChangeLogDetail;
import com.ethink.warehouse.common.mapper.MateInventorySaleChannelChangeLogDetailMapper;
import com.ethink.warehouse.common.mapper.MateInventorySaleChannelChangeLogMapper;
import com.ethink.warehouse.manager.MateInventoryManager;
import com.ethink.warehouse.service.MateInventorySaleChannelChangeLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 库存货权变更 Facade接口实现
 *
 * @author default
 * @date 2023-01-06
 */
@RestController
@Slf4j
@RequestMapping("warehouse-service/facade/v1/mateInventorySaleChannelChangeLog")
public class MateInventorySaleChannelChangeLogFacadeImpl implements MateInventorySaleChannelChangeLogFacade {

    @Autowired
    private MateInventorySaleChannelChangeLogService mateInventorySaleChannelChangeLogService;
    @Autowired
    private MateInventorySaleChannelChangeLogMapper mateInventorySaleChannelChangeLogMapper;
    @Autowired
    private MateInventorySaleChannelChangeLogDetailMapper mateInventorySaleChannelChangeLogDetailMapper;
    @Autowired
    private MateInventoryManager mateInventoryManager;

    @Override
    public Page<MateInventorySaleChannelChangeLogInfo> queryMateInventorySaleChannelChangeLog(MateInventorySaleChannelChangeLogQueryRequest request) {
        return mateInventorySaleChannelChangeLogService.queryMateInventorySaleChannelChangeLog(request);
    }

    @Override
    public MateInventorySaleChannelChangeLogGetDetailResponse getMateInventorySaleChannelChangeLogById(Long mateInventorySaleChannelChangeLogId) {
        return mateInventorySaleChannelChangeLogService.getMateInventorySaleChannelChangeLogById(mateInventorySaleChannelChangeLogId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MateInventorySaleChannelChangeLogAddResponse addMateInventorySaleChannelChangeLog(MateInventorySaleChannelChangeLogAddRequest request) {
        MateInventorySaleChannelChangeLogAddResponse response = mateInventorySaleChannelChangeLogService.addMateInventorySaleChannelChangeLog(request);
        if (MateInventorySaleChannelChangeLogOrderStatusEnum.S2.eq(request.getOrderStatus())) {
            lock(response.getId());
        }
        return response;
    }

    private void lock(Long id) {
        // 锁定库存
        MateInventorySaleChannelChangeLog changeLog = mateInventorySaleChannelChangeLogMapper.selectById(id);
        List<MateInventorySaleChannelChangeLogDetail> changeLogDetails = mateInventorySaleChannelChangeLogDetailMapper.selectList(
                new LambdaQueryWrapper<MateInventorySaleChannelChangeLogDetail>()
                        .eq(MateInventorySaleChannelChangeLogDetail::getOrderNo, changeLog.getOrderNo())
        );
        List<MateInventoryLockLogAddRequest> requests = new ArrayList<>();
        for (MateInventorySaleChannelChangeLogDetail changeLogDetail : changeLogDetails) {
            MateInventoryLockLogAddRequest request = new MateInventoryLockLogAddRequest();
            request.setOrderType(LogisticsTraceDetailOrderTypeEnum.T2.getIntValue());
            request.setSourceOrderNo(changeLog.getOrderNo());
            request.setSourceDetailOrderNo(changeLog.getOrderNo() + changeLogDetail.getId());
            request.setSourceOrderType(SubjectEnum.T112.getCode());
            request.setSubject(SubjectEnum.T112.getCode());
            request.setMateInventoryId(changeLogDetail.getBeforeMateInventoryId());
            request.setLockQty(changeLogDetail.getQty());
            requests.add(request);
        }
        mateInventoryManager.lockMateInventory(requests);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MateInventorySaleChannelChangeLogUpdateResponse updateMateInventorySaleChannelChangeLog(MateInventorySaleChannelChangeLogUpdateRequest request) {
        MateInventorySaleChannelChangeLogUpdateResponse response = mateInventorySaleChannelChangeLogService.updateMateInventorySaleChannelChangeLog(request);
        if (MateInventorySaleChannelChangeLogOrderStatusEnum.S2.eq(request.getOrderStatus())) {
            lock(response.getId());
        }
        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MateInventorySaleChannelChangeLogDeleteResponse deleteMateInventorySaleChannelChangeLog(Long mateInventorySaleChannelChangeLogId) {
        MateInventorySaleChannelChangeLog changeLog = mateInventorySaleChannelChangeLogMapper.selectById(mateInventorySaleChannelChangeLogId);
        if (MateInventorySaleChannelChangeLogOrderStatusEnum.S2.eq(changeLog.getOrderStatus())) {
            // 需要释放库存
            List<MateInventorySaleChannelChangeLogDetail> changeLogDetails = mateInventorySaleChannelChangeLogDetailMapper.selectList(
                    new LambdaQueryWrapper<MateInventorySaleChannelChangeLogDetail>()
                            .eq(MateInventorySaleChannelChangeLogDetail::getOrderNo, changeLog.getOrderNo())
            );
            List<MateInventoryLockLogAddRequest> requests = new ArrayList<>();
            for (MateInventorySaleChannelChangeLogDetail changeLogDetail : changeLogDetails) {
                MateInventoryLockLogAddRequest request = new MateInventoryLockLogAddRequest();
                request.setOrderType(LogisticsTraceDetailOrderTypeEnum.T2.getIntValue());
                request.setSourceOrderNo(changeLog.getOrderNo());
                request.setSourceDetailOrderNo(changeLog.getOrderNo() + changeLogDetail.getId());
                request.setSourceOrderType(SubjectEnum.T112.getCode());
                request.setSubject(SubjectEnum.T112.getCode());
                request.setMateInventoryId(changeLogDetail.getBeforeMateInventoryId());
                request.setLockQty(changeLogDetail.getQty());
                requests.add(request);
            }
            mateInventoryManager.releaseLockMateInventory(requests);
        }
        return mateInventorySaleChannelChangeLogService.deleteMateInventorySaleChannelChangeLog(mateInventorySaleChannelChangeLogId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approvedMateInventorySaleChannelChangeLog(Long id) {
        MateInventorySaleChannelChangeLog changeLog = mateInventorySaleChannelChangeLogMapper.selectById(id);
        if (!MateInventorySaleChannelChangeLogOrderStatusEnum.S2.eq(changeLog.getOrderStatus())) {
            throw new BusinessException(CommonRespCode.SYSTEM_ERR, "当前订单状态无法审批通过");
        }
        List<MateInventorySaleChannelChangeLogDetail> changeLogDetails = mateInventorySaleChannelChangeLogDetailMapper.selectList(
                new LambdaQueryWrapper<MateInventorySaleChannelChangeLogDetail>()
                        .eq(MateInventorySaleChannelChangeLogDetail::getOrderNo, changeLog.getOrderNo())
        );
        mateInventorySaleChannelChangeLogService.approvedMateInventorySaleChannelChangeLog(id);
        // 释放库存
        List<MateInventoryLockLogAddRequest> requests = new ArrayList<>();
        for (MateInventorySaleChannelChangeLogDetail changeLogDetail : changeLogDetails) {
            MateInventoryLockLogAddRequest request = new MateInventoryLockLogAddRequest();
            request.setOrderType(LogisticsTraceDetailOrderTypeEnum.T2.getIntValue());
            request.setSourceOrderNo(changeLog.getOrderNo());
            request.setSourceDetailOrderNo(changeLog.getOrderNo() + changeLogDetail.getId());
            request.setSourceOrderType(SubjectEnum.T112.getCode());
            request.setSubject(SubjectEnum.T112.getCode());
            request.setMateInventoryId(changeLogDetail.getBeforeMateInventoryId());
            request.setLockQty(changeLogDetail.getQty());
            requests.add(request);
        }
        mateInventoryManager.releaseLockMateInventory(requests);
        // 出库,入库
        Map<Long, Long> map = mateInventoryManager.changeMateInventorySaleChannel(changeLog, changeLogDetails);
        map.forEach((detailId, afterMateInventoryId) -> {
            mateInventorySaleChannelChangeLogDetailMapper.update(null,
                    new LambdaUpdateWrapper<MateInventorySaleChannelChangeLogDetail>()
                            .eq(MateInventorySaleChannelChangeLogDetail::getId, detailId)
                            .set(MateInventorySaleChannelChangeLogDetail::getAfterMateInventoryId, afterMateInventoryId)
            );
        });
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void refuseMateInventorySaleChannelChangeLog(Long id) {
        MateInventorySaleChannelChangeLog changeLog = mateInventorySaleChannelChangeLogMapper.selectById(id);
        if (!MateInventorySaleChannelChangeLogOrderStatusEnum.S2.eq(changeLog.getOrderStatus())) {
            throw new BusinessException(CommonRespCode.SYSTEM_ERR, "当前订单状态无法审批拒绝");
        }
        List<MateInventorySaleChannelChangeLogDetail> changeLogDetails = mateInventorySaleChannelChangeLogDetailMapper.selectList(
                new LambdaQueryWrapper<MateInventorySaleChannelChangeLogDetail>()
                        .eq(MateInventorySaleChannelChangeLogDetail::getOrderNo, changeLog.getOrderNo())
        );
        mateInventorySaleChannelChangeLogService.refuseMateInventorySaleChannelChangeLog(id);
        // 释放库存
        List<MateInventoryLockLogAddRequest> requests = new ArrayList<>();
        for (MateInventorySaleChannelChangeLogDetail changeLogDetail : changeLogDetails) {
            MateInventoryLockLogAddRequest request = new MateInventoryLockLogAddRequest();
            request.setOrderType(LogisticsTraceDetailOrderTypeEnum.T2.getIntValue());
            request.setSourceOrderNo(changeLog.getOrderNo());
            request.setSourceDetailOrderNo(changeLog.getOrderNo() + changeLogDetail.getId());
            request.setSourceOrderType(SubjectEnum.T112.getCode());
            request.setSubject(SubjectEnum.T112.getCode());
            request.setMateInventoryId(changeLogDetail.getBeforeMateInventoryId());
            request.setLockQty(changeLogDetail.getQty());
            requests.add(request);
        }
        mateInventoryManager.releaseLockMateInventory(requests);
    }

    @Override
    public Page<MateInventorySaleChannelChangeLogModeInfo> queryMateInventorySaleChannelChangeModeLog(MateInventorySaleChannelChangeLogQueryRequest request) {
        return mateInventorySaleChannelChangeLogService.queryMateInventorySaleChannelChangeModeLog(request);
    }
}